home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Src / LINEconsole / badness.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  15.7 KB  |  739 lines

  1. /* badness.c: routines calculating and using "badness" */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/badness.c,v 6.0 1991/12/18 20:26:30 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Src/LINEconsole/RCS/badness.c,v 6.0 1991/12/18 20:26:30 jpo Rel $
  9.  *
  10.  * $Log: badness.c,v $
  11.  * Revision 6.0  1991/12/18  20:26:30  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. #include    "console.h"
  19.  
  20. #define    DEFAULT_TOTAL_NUMBER    10000.0
  21. #define DEFAULT_TOTAL_VOLUME    1000000.0
  22. static struct tailor    *tailors = NULL;
  23. extern double     atof();
  24. extern char    tailorfile[];
  25. extern int    max_vert_lines;
  26. extern time_t   currentTime;
  27. double    ub_total_number = DEFAULT_TOTAL_NUMBER, 
  28.     ub_total_volume = DEFAULT_TOTAL_VOLUME;
  29.  
  30. /*   */
  31.  
  32. static double    parse_ub(ub)
  33. char    *ub;
  34. {
  35.     double    pre;
  36.     char c;
  37.     
  38.     switch (sscanf(ub, "%lf%c", &pre, &c)) {
  39.         case 1:
  40.         return pre;
  41.         case 2:
  42.         switch    (c) {
  43.             case 'h':
  44.             pre *= 60.0;
  45.             break;
  46.             case 'd':
  47.             pre *= 24.0 * 60.0;
  48.             break;
  49.             case 'k':
  50.             pre *= 1000.0;
  51.             break;
  52.             case 'M':
  53.             pre *= 1000000.0;
  54.             break;
  55.             default:
  56.             break;
  57.         }
  58.         break;
  59.         default:
  60.         return 0.0;
  61.     }
  62.     return    pre;
  63. }
  64.  
  65. static void    add_total_ubs(entry)
  66. char    *entry;        
  67. {
  68.     char    *ix, *str, *margv[20];
  69.     int    i, margc;
  70.     char    *buf = strdup(entry);
  71.     
  72.     if ((ix = index(buf, ':')) == NULL) {
  73.         PP_LOG(LLOG_EXCEPTIONS,
  74.                ("Incorrect console tailor file entry '%s'",buf));
  75.         free(buf);
  76.         return;
  77.     }
  78.     ix++;
  79.     (void) compress(ix, ix);
  80.     margc = sstr2arg(ix, 20, margv, ",");
  81.     i = 0;
  82.     while (i < margc) {
  83.         if ((ix = index(margv[i], '<')) != NULL) {
  84.             *ix = '\0';
  85.             str = margv[i];
  86.             ix++;
  87.             while(*ix != '\0' && isspace(*ix)) ix++;
  88.             while(*str != '\0' && isspace(*str)) str++;
  89.             if (*ix == '\0' || *str == '\0')
  90.                 return;
  91.             if (strncmp(str, "num", 3) == 0)
  92.                 ub_total_number = parse_ub(ix);
  93.             else if (strncmp(str, "vol", 3) == 0)
  94.                 ub_total_volume = parse_ub(ix);
  95.             else
  96.                 PP_LOG(LLOG_EXCEPTIONS,
  97.                        ("Unknown console tailor variable '%s'",
  98.                     str));
  99.         }
  100.         i++;
  101.     }
  102.     free(buf);
  103. }
  104.     
  105. static struct tailor    *tailor_new(entry)
  106. char    *entry;
  107. {
  108.     struct tailor     *ret;
  109.     char        *ix, *str, *margv[20];
  110.     int        i, margc;
  111.     char        *buf = strdup(entry);
  112.     ret = (struct tailor *) calloc(1, sizeof(*ret));
  113.  
  114.     if ((ix = index(buf, ':')) == NULL) {
  115.         PP_LOG(LLOG_EXCEPTIONS,
  116.                ("Incorrect console tailor file entry '%s'",buf));
  117.         free((char *) ret);
  118.         free(buf);
  119.         return NULL;
  120.     }
  121.     *ix = '\0';
  122.     ret->key = strdup(buf);
  123.     ix++;
  124.     (void) compress(ix, ix);
  125.     margc = sstr2arg(ix, 20, margv, ",");
  126.  
  127.     i = 0;
  128.     while (i < margc) {
  129.         if ((ix = index(margv[i], '<')) != NULL) {
  130.             *ix = '\0';
  131.             str = margv[i];
  132.             ix++;
  133.             while (*ix != '\0' && isspace(*ix)) ix++;
  134.             while (*str != '\0' && isspace(*str)) str++;
  135.             if (*ix == '\0' || *str == '\0')
  136.                 return NULL;
  137.  
  138.             if (strncmp(str, "num", 3) == 0) 
  139.                 ret->ub_number = parse_ub(ix);
  140.             else if (strncmp(str, "vol", 3) == 0) 
  141.                 ret->ub_volume = parse_ub(ix);
  142.             else if (strncmp(str, "age", 3) == 0) 
  143.                 ret->ub_age = parse_ub(ix);
  144.             else if (strncmp(str, "las", 3) == 0) 
  145.                 ret->ub_last = parse_ub(ix);
  146.             else
  147.                 PP_LOG(LLOG_EXCEPTIONS,
  148.                        ("Unknown console tailor variable '%s'",
  149.                     str));
  150.         }
  151.         i++;
  152.     }
  153.     free(buf);
  154.     return ret;
  155. }
  156.  
  157. static void tailor_add(plist, new)
  158. struct tailor    **plist, *new;
  159. {
  160.     new->next = *plist;
  161.     *plist = new;
  162. }
  163.  
  164. void tailor_free(list)
  165. struct tailor    *list;
  166. {
  167.     if (list->key) free(list->key);
  168.     if (list->next) tailor_free(list->next);
  169.     free((char *) list);
  170. }
  171.  
  172. /*   */
  173.  
  174. struct tailor *find_tailor(name, list)
  175. char        *name;
  176. struct tailor    *list;
  177. {
  178.     while (list != NULL
  179.            && strcmp(list->key, name) != 0)
  180.         list = list->next;
  181.     return list;
  182. }
  183.  
  184. /*   */
  185. #include    "tai_defs.inc"
  186. extern char    *myname;
  187.  
  188. static void tailor_add_one_default(plist, type, hardwired)
  189. struct tailor    **plist;
  190. char        *type,
  191.         *hardwired;
  192. {
  193.     if (find_tailor(type, *plist) == NULL) 
  194.         tailor_add(plist,tailor_new(hardwired));
  195. }
  196.  
  197. static void tailor_add_defaults(plist)
  198. struct tailor    **plist;
  199. {
  200.     /* mts defaults */
  201.     tailor_add_one_default(plist, "mtsin-chan", default_mtsin_chan);
  202.     tailor_add_one_default(plist, "mtsout-chan", default_mtsout_chan);
  203.     tailor_add_one_default(plist, "mtsboth-chan", default_mtsboth_chan);
  204.     tailor_add_one_default(plist, "mtsin-mta", default_mtsin_mta);
  205.     tailor_add_one_default(plist, "mtsout-mta", default_mtsout_mta);
  206.      tailor_add_one_default(plist, "mtsboth-mta", default_mtsboth_mta);
  207.      tailor_add_one_default(plist, "mtsin-msg", default_mtsin_msg);
  208.     tailor_add_one_default(plist, "mtsout-msg", default_mtsout_msg);
  209.     tailor_add_one_default(plist, "mtsboth-msg", default_mtsboth_msg);
  210.     
  211.     /* mta defaults */
  212.     tailor_add_one_default(plist, "mtain-chan", default_mtain_chan);
  213.     tailor_add_one_default(plist, "mtaout-chan", default_mtaout_chan);
  214.     tailor_add_one_default(plist, "mtaboth-chan", default_mtaboth_chan);
  215.     tailor_add_one_default(plist, "mtain-mta", default_mtain_mta);
  216.     tailor_add_one_default(plist, "mtaout-mta", default_mtaout_mta);
  217.     tailor_add_one_default(plist, "mtaboth-mta", default_mtaboth_mta);
  218.     tailor_add_one_default(plist, "mtain-msg", default_mtain_msg);
  219.     tailor_add_one_default(plist, "mtaout-msg", default_mtaout_msg);
  220.     tailor_add_one_default(plist, "mtaboth-msg", default_mtaboth_msg);
  221.  
  222.     /* internal defaults */
  223.     tailor_add_one_default(plist, "internal-chan", default_internal_chan);
  224.     tailor_add_one_default(plist, "internal-mta", default_internal_mta);
  225.     tailor_add_one_default(plist, "internal-msg", default_internal_msg);
  226.     
  227.     /* passive defaults */
  228.     tailor_add_one_default(plist, "passive-chan", default_passive_chan);
  229.     tailor_add_one_default(plist, "passive-mta", default_passive_mta);
  230.     tailor_add_one_default(plist, "passive-msg", default_passive_msg);
  231. }
  232.  
  233.  
  234. /*   */
  235.  
  236. TaiInit()
  237. {
  238.     FILE    *fp = NULL;
  239.     char    buf[BUFSIZ];
  240.  
  241.     if (tailors) {
  242.         tailor_free(tailors);
  243.         tailors = NULL;
  244.     }
  245.     /* read in console tailor file */
  246.     if (tailorfile[0] != '\0') {
  247.         if ((fp  = fopen(tailorfile, "r")) == NULL
  248.             && tailorfile[0] != '/') {
  249.             char    *home;
  250.             /* try relative to home directory */
  251.             if ((home = getenv("HOME")) != NULLCP) {
  252.                 (void) sprintf(buf, "%s/%s",
  253.                            home, tailorfile);
  254.                 fp = fopen(buf, "r");
  255.             }
  256.         }
  257.         
  258.         if (fp != NULL) {
  259.             while (fgets(buf, BUFSIZ, fp) != NULLCP) {
  260.                 (void) compress(buf, buf);
  261.                 if (buf[0] == '\n' || buf[0] == '\0' 
  262.                     || buf[0] == '#') 
  263.                     continue;
  264.                 if (strncmp(buf,"totals", strlen("totals")) == 0)
  265.                     add_total_ubs(buf);
  266.                 else
  267.                     tailor_add(&tailors, tailor_new(buf));
  268.             }
  269.             fclose(fp);
  270.         }
  271.     }
  272.     tailor_add_defaults(&tailors);
  273. }
  274.  
  275. /*   */
  276.  
  277. add_tailor_to_chan(chan)
  278. struct chan_struct    *chan;
  279. {
  280.     char    buf[BUFSIZ];
  281.     
  282.     sprintf(buf, "%s-chan", chan->channelname);
  283.     
  284.     if ((chan->tai = find_tailor(buf, tailors)) == NULL) {
  285.         /* no explicit try defaults */
  286.  
  287.         char    *type = NULL,
  288.             *dir = NULL;
  289.  
  290.         switch (chan->chantype) {
  291.             case int_Qmgr_chantype_mta:
  292.             type = strdup("mta");
  293.             if (chan->outbound > 0 && chan->inbound > 0)
  294.                 dir = strdup("both");
  295.             else if (chan->inbound > 0)
  296.                 dir = strdup("in");
  297.             else if (chan->outbound > 0)
  298.                 dir = strdup("out");
  299.             break;
  300.  
  301.             case int_Qmgr_chantype_mts:
  302.             type = strdup("mts");
  303.             if (chan->outbound > 0 && chan->inbound > 0)
  304.                 dir = strdup("both");
  305.             else if (chan->inbound > 0)
  306.                 dir = strdup("in");
  307.             else if (chan->outbound > 0)
  308.                 dir = strdup("out");
  309.             break;
  310.  
  311.             case int_Qmgr_chantype_internal:
  312.             type = strdup("internal");
  313.             break;
  314.  
  315.             case int_Qmgr_chantype_passive:
  316.             default:
  317.             type = strdup("passive");
  318.             break;
  319.         }
  320.  
  321.         sprintf(buf, "%s%s-chan",
  322.             type,
  323.             (dir == NULL) ? "" : dir);
  324.  
  325.         if (type) free(type);
  326.         if (dir) free(dir);
  327.         chan->tai = find_tailor(buf, tailors);
  328.     }
  329. }
  330.         
  331. add_tailor_to_mta(chan, mta)
  332. struct chan_struct    *chan;
  333. struct mta_struct    *mta;
  334. {
  335.     char    buf[BUFSIZ];
  336.     
  337.     sprintf(buf, "%s-mta", chan->channelname);
  338.     
  339.     if ((mta->tai = find_tailor(buf, tailors)) == NULL) {
  340.         /* no explicit try defaults */
  341.  
  342.         char    *type = NULL,
  343.             *dir = NULL;
  344.  
  345.         switch (chan->chantype) {
  346.             case int_Qmgr_chantype_mta:
  347.             type = strdup("mta");
  348.             if (chan->outbound > 0 && chan->inbound > 0)
  349.                 dir = strdup("both");
  350.             else if (chan->inbound > 0)
  351.                 dir = strdup("in");
  352.             else if (chan->outbound > 0)
  353.                 dir = strdup("out");
  354.             break;
  355.  
  356.             case int_Qmgr_chantype_mts:
  357.             type = strdup("mts");
  358.             if (chan->outbound > 0 && chan->inbound > 0)
  359.                 dir = strdup("both");
  360.             else if (chan->inbound > 0)
  361.                 dir = strdup("in");
  362.             else if (chan->outbound > 0)
  363.                 dir = strdup("out");
  364.             break;
  365.  
  366.             case int_Qmgr_chantype_internal:
  367.             type = strdup("internal");
  368.             break;
  369.  
  370.             case int_Qmgr_chantype_passive:
  371.             default:
  372.             type = strdup("passive");
  373.             break;
  374.         }
  375.  
  376.         sprintf(buf, "%s%s-mta",
  377.             type,
  378.             (dir == NULL) ? "" : dir);
  379.  
  380.         if (type) free(type);
  381.         if (dir) free(dir);
  382.         mta->tai = find_tailor(buf, tailors);
  383.     }
  384. }
  385.  
  386. add_tailor_to_msg(chan, msg)
  387. struct chan_struct    *chan;
  388. struct msg_struct    *msg;
  389. {
  390.     char    buf[BUFSIZ];
  391.     
  392.     if (chan == NULL)
  393.         return;
  394.  
  395.     sprintf(buf, "%s-msg", chan->channelname);
  396.     
  397.     if ((msg->tai = find_tailor(buf, tailors)) == NULL) {
  398.         /* no explicit try defaults */
  399.  
  400.         char    *type = NULL,
  401.             *dir = NULL;
  402.  
  403.         switch (chan->chantype) {
  404.             case int_Qmgr_chantype_mta:
  405.             type = strdup("mta");
  406.             if (chan->outbound > 0 && chan->inbound > 0)
  407.                 dir = strdup("both");
  408.             else if (chan->inbound > 0)
  409.                 dir = strdup("in");
  410.             else if (chan->outbound > 0)
  411.                 dir = strdup("out");
  412.             break;
  413.  
  414.             case int_Qmgr_chantype_mts:
  415.             type = strdup("mts");
  416.             if (chan->outbound > 0 && chan->inbound > 0)
  417.                 dir = strdup("both");
  418.             else if (chan->inbound > 0)
  419.                 dir = strdup("in");
  420.             else if (chan->outbound > 0)
  421.                 dir = strdup("out");
  422.             break;
  423.  
  424.             case int_Qmgr_chantype_internal:
  425.             type = strdup("internal");
  426.             break;
  427.  
  428.             case int_Qmgr_chantype_passive:
  429.             default:
  430.             type = strdup("passive");
  431.             break;
  432.         }
  433.  
  434.         sprintf(buf, "%s%s-msg",
  435.             type,
  436.             (dir == NULL) ? "" : dir);
  437.  
  438.         if (type) free(type);
  439.         if (dir) free(dir);
  440.         msg->tai = find_tailor(buf, tailors);
  441.     }
  442. }
  443.  
  444. /*   */
  445.  
  446. int volBadness(vol)
  447. int    vol;
  448. {
  449.     int    retval = 0;
  450.     if (ub_total_volume != 0.0)
  451.         retval = (int) (vol*100/ub_total_volume);
  452.     if (vol != 0 && retval == 0)
  453.         retval = 1;
  454.     return retval;
  455. }
  456.  
  457. int numBadness(num)
  458. int    num;
  459. {
  460.     int     retval = 0;
  461.     if (ub_total_number != 0.0) 
  462.         retval = (int) (num*100/ub_total_number);
  463.     if (num != 0 && retval == 0)
  464.         return 1;
  465.     return retval;
  466. }
  467.  
  468. int chanBadness(chan)
  469. struct chan_struct    *chan;
  470. {
  471.     double        average_db = 0.0,
  472.             age,
  473.             last;
  474.     
  475.     int        average = 0,
  476.             noFactors = 0;
  477.  
  478.     register struct tailor    *tai = chan->tai;
  479.  
  480.     if (tai == NULL) {
  481.         PP_LOG(LLOG_EXCEPTIONS,
  482.                ("No tailoring for channel '%s'", chan->channelname));
  483.         return 0;
  484.     }
  485.  
  486.     if (chan->inbound <= 0 
  487.         && chan->numberMessages == 0 
  488.         && chan->numberReports == 0)
  489.         return 0;
  490.  
  491.     if (tai->ub_number != 0.0) {
  492.         if ((chan->numberMessages + chan->numberReports) >= tai->ub_number)
  493.             return max_bad_channel;
  494.         average_db += ((chan->numberMessages+chan->numberReports) * 100)/ tai->ub_number;
  495.         noFactors++;
  496.     }
  497.  
  498.     if (tai->ub_volume != 0.0) {
  499.         if (chan->volumeMessages >= tai->ub_volume)
  500.             return max_bad_channel;
  501.         average_db += (chan->volumeMessages * 100)/tai->ub_volume;
  502.         noFactors++;
  503.     }
  504.  
  505.     if (tai->ub_age != 0.0) {
  506.         if (chan->oldestMessage != 0 && 
  507.             (chan->numberMessages != 0 || chan->numberReports != 0))
  508.             age = (currentTime-chan->oldestMessage) / 60.0;
  509.         else
  510.             age = 0.0;
  511.         if (age >= tai->ub_age)
  512.             return max_bad_channel;
  513.         average_db += (age * 100)/tai->ub_age;
  514.         noFactors++;
  515.     }
  516.  
  517.     if (tai->ub_last != 0.0) {
  518.         if (chan->status->lastSuccess != 0)
  519.             last = (currentTime - chan->status->lastSuccess)/60.0;
  520.         else
  521.             last = 0.0;
  522.         if (last >= tai->ub_last)
  523.             return max_bad_channel;
  524.         if (last >= tai->ub_last/2) {
  525.             average_db += (last * 100)/tai->ub_last;
  526.             noFactors++;
  527.         }
  528.     }
  529.  
  530.     /* scale up those that don't use all factors */
  531.     if (noFactors != 0)
  532.         average = (int) (average_db * max_bad_channel / (noFactors * 100));
  533.  
  534.     if (average == 0 && average_db != 0.0)
  535.         return 1;
  536.     return average;
  537. }
  538.  
  539. /*   */
  540.  
  541. int mtaBadness(mta)
  542. struct mta_struct    *mta;
  543. {
  544.     double        average_db = 0.0,
  545.             age,
  546.             last;
  547.     
  548.     int        average = 0,
  549.             noFactors = 0;
  550.  
  551.     register struct tailor    *tai = mta->tai;
  552.  
  553.     if (tai == NULL) {
  554.         PP_LOG(LLOG_EXCEPTIONS,
  555.                ("No tailoring for mta '%s'", mta->mta));
  556.         return 0;
  557.     }
  558.  
  559.     if (mta->numberMessages == 0 && mta->numberReports == 0)
  560.         return 0;
  561.  
  562.     if (tai->ub_number != 0.0) {
  563.         if (mta->numberMessages+mta->numberReports >= tai->ub_number)
  564.             return max_bad_mta;
  565.         average_db += ((mta->numberMessages+mta->numberReports) * 100)/ tai->ub_number;
  566.         noFactors++;
  567.     }
  568.  
  569.     if (tai->ub_volume != 0.0) {
  570.         if (mta->volumeMessages >= tai->ub_volume)
  571.             return max_bad_mta;
  572.         average_db += (mta->volumeMessages * 100)/tai->ub_volume;
  573.         noFactors++;
  574.     }
  575.  
  576.     if (tai->ub_age != 0.0) {
  577.         if (mta->oldestMessage != 0 
  578.             && (mta->numberMessages != 0 || mta->numberReports != 0))
  579.             age = (currentTime-mta->oldestMessage) / 60.0;
  580.         else
  581.             age = 0;
  582.         if (age >= tai->ub_age)
  583.             return max_bad_mta;
  584.         average_db += (age * 100)/tai->ub_age;
  585.         noFactors++;
  586.     }
  587.  
  588.     if (tai->ub_last != 0.0) {
  589.         if (mta->status->lastSuccess != 0)
  590.             last = (currentTime - mta->status->lastSuccess)/60.0;
  591.         else
  592.             last = 0;
  593.         if (last >= tai->ub_last)
  594.             return max_bad_mta;
  595.         if (last >= tai->ub_last/2) {
  596.             average_db += (last * 100)/tai->ub_last;
  597.             noFactors++;
  598.         }
  599.     }
  600.  
  601.     /* scale up those that don't use all factors */
  602.     if (noFactors != 0)
  603.         average = (int) (average_db * max_bad_mta / (noFactors * 100));
  604.  
  605.     if (average == 0 && average_db != 0.0)
  606.         return 1;
  607.     return average;
  608. }
  609.  
  610. /*   */
  611.  
  612. int msgBadness(msg)
  613. struct msg_struct    *msg;
  614. {
  615.     double        average_db = 0.0,
  616.             age;
  617.     
  618.     int        average = 0,
  619.             noFactors = 0;
  620.  
  621.     register struct tailor    *tai = msg->tai;
  622.  
  623.     if (tai == NULL) {
  624.         PP_LOG(LLOG_EXCEPTIONS,
  625.                ("No tailoring for msg '%s'", msg->msginfo->queueid));
  626.         return 0;
  627.     }
  628.  
  629.     if (msg->msginfo->expiryTime != 0
  630.         && (currentTime - msg->msginfo->expiryTime) >= 0)
  631.         /* expired so max_bad_msg ?? */
  632.         return max_bad_msg;
  633.  
  634.     if (tai->ub_age != 0.0) {
  635.         age = (currentTime-msg->msginfo->age) / 60.0;
  636.         if (age >= tai->ub_age)
  637.             return max_bad_msg;
  638.         average_db += (age * 100)/tai->ub_age;
  639.         noFactors++;
  640.     }
  641.  
  642.     if (tai->ub_volume != 0.0) {
  643.         if (msg->msginfo->size > tai->ub_volume)
  644.             return max_bad_msg;
  645.         average_db += (msg->msginfo->size * 100) / tai->ub_volume;
  646.         noFactors++;
  647.     }
  648.  
  649.     /* scale up those that don't use all factors */
  650.     if (noFactors != 0)
  651.         average = (int) (average_db * max_bad_msg / (noFactors * 100));
  652.     if (average == 0 && average_db != 0.0)
  653.         return 1;
  654.     return average;
  655. }
  656.  
  657. /*   */
  658.  
  659. /* ordering routines */
  660.  
  661. static int channel_compare(one, two)
  662. struct chan_struct    **one,
  663.             **two;
  664. /* return -1 if one worse state then two */
  665. {
  666.     int    onebad,
  667.         twobad;
  668.     onebad = chanBadness((*one));
  669.     twobad = chanBadness((*two));
  670.     if (onebad < twobad)
  671.         return 1;
  672.     else if (onebad > twobad)
  673.         return -1;
  674.     else 
  675.         return 0;
  676. }
  677.  
  678. order_channels(list, num)
  679. struct chan_struct    **list;
  680. int            num;
  681. /* order display_list */
  682. {
  683.     qsort((char *) &(list[0]),num,
  684.           sizeof(list[0]),(IFP)channel_compare);
  685. }
  686.  
  687.  
  688. static int mta_compare (one, two)
  689. struct mta_struct    **one,
  690.             **two;
  691. /* returns -1 if ione in worse state than two */
  692. {
  693.     int    onebad,
  694.         twobad;
  695.     onebad = mtaBadness((*one));
  696.     twobad = mtaBadness((*two));
  697.     if (onebad < twobad)
  698.         return 1;
  699.     else if (onebad > twobad)
  700.         return -1;
  701.     else 
  702.         return 0;
  703. }
  704.  
  705. order_mtas(plist,num)
  706. struct mta_struct    ***plist;
  707. int            num;
  708. {
  709.     struct mta_struct **temp = *plist;
  710.     qsort((char *)&(temp[0]),num,sizeof(temp[0]),(IFP)mta_compare);
  711. }
  712.  
  713. extern int            number_msgs;
  714. extern struct msg_struct    **global_msg_list;
  715.  
  716. static int msg_compare (one, two)
  717. struct msg_struct    **one,
  718.             **two;
  719. /* returns -1 if ione in worse state than two */
  720. {
  721.     int    onebad,
  722.         twobad;
  723.     onebad = msgBadness((*one));
  724.     twobad = msgBadness((*two));
  725.     if (onebad < twobad)
  726.         return 1;
  727.     else if (onebad > twobad)
  728.         return -1;
  729.     else 
  730.         return 0;
  731. }
  732.  
  733. order_msgs()
  734. {
  735.     qsort((char *) &(global_msg_list[0]),number_msgs,
  736.           sizeof(global_msg_list[0]),(IFP)msg_compare);
  737. }
  738.  
  739.